#!/usr/bin/env python3
#
# trigonometric_function.py
#


from matplotlib.ticker import FuncFormatter
from matplotlib.ticker import MultipleLocator
import matplotlib.pyplot as plt
import numpy as np


def main():

    fig, axs = plt.subplots(1, 3, figsize=(14,4.5))

    axs[0] = configure_axes(axs[0], 'Trigonometric Function\t\t\t' + r'$sine$', 2*np.pi, 1, np.pi, np.pi/2, 1, 1/2)
    x = np.linspace(-2*np.pi, 2*np.pi, 300)
    y = 1/2 * np.sin(2*x + np.pi/3)
    axs[0].plot(x, y, color='b')
    axs[0].text(3.5, 0.5,  r'$y = \frac{1}{2}sin(2x + \frac{π}{3})$',  color='b', horizontalalignment='left',  verticalalignment='bottom')
    y = np.sin(x)
    axs[0].plot(x, y, color='k', linestyle=':')
    axs[0].text(4, -1,  r'$y = sin(x)$',  color='k', horizontalalignment='left',  verticalalignment='top')

    axs[1] = configure_axes(axs[1], '\t\t\t\t\t\t\t' + r'$cosine$', 4*np.pi, 2, np.pi, np.pi/2, 2, 1)
    x = np.linspace(-4*np.pi, 4*np.pi, 300)
    y = 2 * np.cos(1/2*x - np.pi*2/3)
    axs[1].plot(x, y, color='r')
    axs[1].text(14, -2,  r'$y = 2cos(\frac{1}{2}x - \frac{2π}{3})$',  color='r', horizontalalignment='right',  verticalalignment='top')
    y = np.cos(x)
    axs[1].plot(x, y, color='k', linestyle=':')
    axs[1].text(14, 1,  r'$y = cos(x)$',  color='k', horizontalalignment='right',  verticalalignment='bottom')

    axs[2] = configure_axes(axs[2], '\t\t\t\t\t\t\t' + r'$tangent$', 3*np.pi, 5, np.pi, np.pi/2, 5, 2.5)
    x1 = np.linspace(-35/12*np.pi, -13/12*np.pi, 100)
    y1 = np.tan(x1*1/2)
    x2 = np.linspace(-11/12*np.pi,  11/12*np.pi, 100)
    y2 = np.tan(x2*1/2)
    x3 = np.linspace( 13/12*np.pi,  35/12*np.pi, 100)
    y3 = np.tan(x3*1/2)
    axs[2].plot(x1, y1, x2, y2, x3, y3, color='y')
    axs[2].text(9, 7,  r'$y = tan(\frac{1}{2}x)$',  color='y', horizontalalignment='right',  verticalalignment='bottom')
    x1 = np.linspace(-29/12*np.pi, -19/12*np.pi, 100)
    y1 = np.tan(x1)
    x2 = np.linspace(-17/12*np.pi,  -7/12*np.pi, 100)
    y2 = np.tan(x2)
    x3 = np.linspace( -5/12*np.pi,   5/12*np.pi, 100)
    y3 = np.tan(x3)
    x4 = np.linspace(  7/12*np.pi,  17/12*np.pi, 100)
    y4 = np.tan(x4)
    x5 = np.linspace( 19/12*np.pi,  29/12*np.pi, 100)
    y5 = np.tan(x5)
    axs[2].plot(x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, color='k', linestyle=':')
    axs[2].text(4, -4,  r'$y = tan(x)$',  color='k', horizontalalignment='left',  verticalalignment='top')

    fig.tight_layout()

    plt.show()
    # end of main()


def configure_axes(ax, title, xlimit, ylimit, xmajorunit = 2*np.pi, xminorunit = np.pi, ymajorunit = 1, yminorunit = 1/2):

    ax.set_title(title, fontsize='large', loc='left')

    ax.spines['left'].set_position('zero')
    ax.spines['right'].set_visible(False)
    ax.spines['bottom'].set_position('zero')
    ax.spines['top'].set_visible(False)

    ax.text(-0.2, -0.2, 'O', fontsize='x-large', fontstyle='italic', horizontalalignment='right', verticalalignment='top')

    xlimit += xmajorunit*0.8
    ylimit += ymajorunit*0.8
    ax.set_xlim((-xlimit, xlimit))
    ax.set_ylim((-ylimit, ylimit))

    ax.plot(1, 0, '>k', transform=ax.get_yaxis_transform(), clip_on=False)
    ax.xaxis.set_label_text('x')
    ax.xaxis.set_label_coords(1.01, 0.48)
    ax.xaxis.set_major_formatter(FuncFormatter(lambda w, pos: f'{w:.2f}' if w else ''))
    ax.xaxis.set_major_locator(MultipleLocator(xmajorunit))
    ax.xaxis.set_minor_locator(MultipleLocator(xminorunit))
    ax.xaxis.set_tick_params(which='both', direction='in')

    ax.plot(0, 1, '^k', transform=ax.get_xaxis_transform(), clip_on=False)
    ax.yaxis.set_label_text('y')
    ax.yaxis.set_label_coords(0.48, 1)
    ax.yaxis.label.set_rotation(0)
    ax.yaxis.set_major_formatter(FuncFormatter(lambda w, pos: f'{w:.1f}' if w else ''))
    ax.yaxis.set_major_locator(MultipleLocator(ymajorunit))
    ax.yaxis.set_minor_locator(MultipleLocator(yminorunit))
    ax.yaxis.set_tick_params(which='both', direction='in')

    return ax
    # end of configure_axes()


if __name__ == '__main__': main()

